/********************************************************************************
* @file    app_soft_voltameter.c
* @author  jianqiang.xue
* @version V1.0.0
* @date    2021-07-14
* @brief   软件电量计
* @example 参考[biz_led.c]-[power_bat_check_and_refresh()]
ADC采集回调power_bat_state_handle(),根据充电IC引脚和历史充电数据表进行判断

********************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

#include "log.h"
/* Private Includes ----------------------------------------------------------*/
#include "app_power.h"
#include "app_soft_voltameter.h"
#include "ls_syscfg.h"
#include "ls_gpio.h"
#include "biz_battery_model.h"
/* Private Define ------------------------------------------------------------*/
#define BATTERY_MAX_SOC 100
#define BATTERY_MIN_SOC 0

#define LOG_SWITCH 0
#if LOG_SWITCH == 1
#define APP_LOG LOG_D
#else
#define APP_LOG
#endif

#define FULL_BATTERY_OFFSET 15
/* External Variables --------------------------------------------------------*/
/* Private Variables ---------------------------------------------------------*/
/* Private Function Prototypes -----------------------------------------------*/

/**
 * @brief  查表得到电池soc
 * @param  voltage: 电压值
 * @retval soc
 */
static uint8_t lookup_bat_soc(uint16_t voltage)
{
    uint8_t i;

    if (get_usb_state())
    {
        if (voltage >= get_bat_full_vol_val())
        {
            // LOG_D("calculate_battery_percent full\r\n");
#if LS_CHARGE_SCHEME == 2
            return BATTERY_MAX_SOC;
#else
            // 如果不是软件查表检测满电，则最大值为99
            if (get_charge_state() && get_usb_state())
            {
                set_bat_soc_val(100);
                return BATTERY_MAX_SOC;
            }
            else
            {
                set_bat_soc_val(99);
                return BATTERY_MAX_SOC - 1;
            }
#endif
        }
        else if (voltage > g_battery_data_val[BATTERY_DATA_NUM - 1])
        {
            set_bat_soc_val(99);
            return BATTERY_MAX_SOC - 1;
        }
    }
    else
    {
        if (voltage > g_battery_data_val[BATTERY_DATA_NUM - 1])
        {
            set_bat_soc_val(100);
            return BATTERY_MAX_SOC;
        }
#if LS_CHARGE_SCHEME == 2
#else
        else
        {
            if (get_bat_soc_val() == 100)
            {
                set_bat_soc_val(99);
                return BATTERY_MAX_SOC - 1;
            }
        }
#endif
    }

    for (i = 0; i < BATTERY_DATA_NUM; i++)
    {
        if (voltage <= g_battery_data_val[i])
        {
            if (get_usb_state())
            {
                if (i > 1)
                {
#if LS_BAT_SOC_TYPE == 0
                    return (i - 2);
#elif LS_BAT_SOC_TYPE == 1
                    return (i - 2) * (20);
#elif LS_BAT_SOC_TYPE == 2
                    return (i - 2) * (25);
#elif LS_BAT_SOC_TYPE == 3
                    return (i - 1) * (25);
#endif
                }
                else
                {
                    return BATTERY_MIN_SOC;
                }
            }
            else
            {
                if (i > 0)
                {
                    // LOG_D("<DEBUG> SOC:%d|%d\r\n", i, (i - 1) * (25));
#if LS_BAT_SOC_TYPE == 0
                    return (i - 1);
#elif LS_BAT_SOC_TYPE == 1
                    return (i - 1) * (20);
#elif LS_BAT_SOC_TYPE == 2
                    return (i - 1) * (25);
#elif LS_BAT_SOC_TYPE == 3
                    return (i - 1) * (25);
#endif
                }
                else
                {
                    return BATTERY_MIN_SOC;
                }
            }
        }
    }
    return BATTERY_MIN_SOC;
}

/**
 * @brief  [软电量计] 模拟真实充放电 电池SOC计算事件
 * @note   尽可能接近真实状态
 * @param  first: 是否首次 0--否  1--首次
 */
static void power_bat_sos_handle(bool first)
{
    static uint8_t bat_soc_old = 0;   //记录上次值
    static uint8_t bat_soc_valid = 0; //记录有效次数，决定是否使用

    uint8_t bat_soc = 0;

    bat_soc = lookup_bat_soc(get_bat_vol() - get_bat_vol_offset());
    // 判断是否使用了充电IC
#if LS_CHARGE_SCHEME == 0 || LS_CHARGE_SCHEME == 1 || LS_CHARGE_SCHEME == 4
    if (bat_soc == 100)
    {
        if (get_charge_state() && get_usb_state())
        {
            // LOG_D("<DEBUG> get_charge_state:%d\r\n",bat_soc );
            bat_soc = BATTERY_MAX_SOC;
        }
        else
        {
            bat_soc = BATTERY_MAX_SOC - 1;
        }
    }
#endif

    if (first)
    {
        if (get_bat_soc_val() == BATTERY_MIN_SOC)
        {
            set_bat_soc_val(bat_soc);
            bat_soc_old = bat_soc;
        }
        else
        {
            bat_soc_old = get_bat_soc_val();
        }
        // 当电量计为100时，电池状态置为满
        if (get_bat_soc_val() == BATTERY_MAX_SOC)
        {
            set_bat_state(POWER_FULL_BATTERY);
#if LS_CHARGE_SCHEME == 2
            set_battery_vol_offset((((short)get_bat_full_vol_val() - (short)g_battery_data_val[BATTERY_DATA_NUM - 1]) >> 2));
            set_bat_full_vol_val(get_bat_vol() - FULL_BATTERY_OFFSET);
#endif
            // LOG_D("[battery_sos]battery_state:%d |bat_soc:%d%%\r\n", get_bat_state(), get_bat_soc_val());
        }
    }
    else
    {
        if (get_usb_state())
        {
            if (get_bat_soc_val() != BATTERY_MAX_SOC)
            {
                if (bat_soc > bat_soc_old)
                {
                    // LOG_I("new_bat_soc == %d%% |bat_soc:%d%%|%d\r\n", bat_soc, get_bat_soc_val(), bat_soc_valid);
                    if (bat_soc / bat_soc_old > 4)
                    {
                        bat_soc_valid += 4;
                    }
                    else if (bat_soc / bat_soc_old > 3)
                    {
                        bat_soc_valid += 3;
                    }
                    else if (bat_soc / bat_soc_old > 2)
                    {
                        bat_soc_valid += 2;
                    }
                    else
                    {
                        bat_soc_valid++;
                    }
                }
                else if (bat_soc_old <= bat_soc)
                {
                    bat_soc_valid = 0;
                }
#if LS_BAT_SOC_TYPE == 0 || LS_BAT_SOC_TYPE == 1 || LS_BAT_SOC_TYPE == 2
                if (bat_soc_valid < 1)
                {
                    return;
                }
                // 根据soc改变电量刷新速率
                if ((get_bat_soc_val() <= 10 && bat_soc_valid > 5) ||
                    (get_bat_soc_val() <= 30 && bat_soc_valid > 5) ||
                    (get_bat_soc_val() <= 50 && bat_soc_valid > 2) ||
                    (get_bat_soc_val() <= 60 && bat_soc_valid > 2) ||
                    (get_bat_soc_val() <= 70 && bat_soc_valid > 3) ||
                    (get_bat_soc_val() <= 80 && bat_soc_valid > 3) ||
                    (get_bat_soc_val() <= 90 && bat_soc_valid > 4) ||
                    (get_bat_soc_val() <= 95 && bat_soc_valid > 4) ||
                    (get_bat_soc_val() <= 100 && bat_soc_valid > 5))
#endif
                {
                    bat_soc_valid = 0;
#if LS_BAT_SOC_TYPE == 0
                    increment_bat_soc_val((bat_soc > get_bat_soc_val()) ? 1 : 0);
#elif LS_BAT_SOC_TYPE == 1
                    increment_bat_soc_val((bat_soc > get_bat_soc_val()) ? (20) : 0);
#elif LS_BAT_SOC_TYPE == 2
                    increment_bat_soc_val((bat_soc > get_bat_soc_val()) ? (25) : 0);
#elif LS_BAT_SOC_TYPE == 3
                    increment_bat_soc_val((bat_soc > get_bat_soc_val()) ? (25) : 0);
#endif
                    // LOG_D("bat_soc_old:%d |bat_soc:%d%%\r\n", bat_soc_old, bat_soc);
                    bat_soc_old = get_bat_soc_val();
                }
            }
            else
            {
                // 当电量计为100时，电池状态置为满
                set_bat_state(POWER_FULL_BATTERY);
#if LS_CHARGE_SCHEME == 2
                set_bat_vol_offset((((short)get_bat_full_vol_val() - (short)g_bat_data_val[BATTERY_DATA_NUM - 1]) >> 2));
                set_bat_full_vol_val(get_bat_vol() - FULL_BATTERY_OFFSET);
#endif
                // LOG_D("[battery_sos]battery_state:%d |bat_soc:%d%%\r\n", get_bat_state(), get_bat_soc_val());
            }
        }
        else
        {
            if (get_bat_soc_val() == 0)
            {
                return;
            }
            if (bat_soc < bat_soc_old)
            {
                // LOG_I("new_bat_soc == %d |bat_soc:%d%%|%d\r\n", bat_soc, get_bat_soc_val(), bat_soc_valid);
                bat_soc_valid++;
            }
#if LS_BAT_SOC_TYPE == 0 || LS_BAT_SOC_TYPE == 1 || LS_BAT_SOC_TYPE == 2
            else if (bat_soc_old >= bat_soc)
            {
                bat_soc_valid = 0;
            }

            if (bat_soc_valid < 1)
            {
                return;
            }
            // 根据soc改变电量刷新速率
            if ((bat_soc <= 15 && bat_soc_valid > 1) ||
                (bat_soc <= 20 && bat_soc_valid > 1) ||
                (bat_soc <= 30 && bat_soc_valid > 2) ||
                (bat_soc <= 40 && bat_soc_valid > 3) ||
                (bat_soc <= 60 && bat_soc_valid > 3) ||
                (bat_soc <= 80 && bat_soc_valid > 4) ||
                (bat_soc <= 90 && bat_soc_valid > 4) ||
                (bat_soc <= 95 && bat_soc_valid > 6) ||
                (bat_soc <= 100 && bat_soc_valid > 10))
#endif
            {
                bat_soc_valid = 0;
#if LS_BAT_SOC_TYPE == 0
                reduce_bat_soc_val((bat_soc < get_bat_soc_val()) ? 1 : 0);
#elif LS_BAT_SOC_TYPE == 1
                reduce_bat_soc_val((bat_soc < get_bat_soc_val()) ? (20) : 0);
#elif LS_BAT_SOC_TYPE == 2
                reduce_bat_soc_val((bat_soc < get_bat_soc_val()) ? (25) : 0);
#elif LS_BAT_SOC_TYPE == 3
                reduce_bat_soc_val((bat_soc < get_bat_soc_val()) ? (25) : 0);
#endif
                bat_soc_old = get_bat_soc_val();
                // LOG_D("<DEBUG> bat_soc_old:%d |bat_soc:%d%%\r\n", bat_soc_old, bat_soc);
            }
        }
    }
}

/**
 * @brief  [软电量计] 模拟真实充放电 电池状态事件
 * @note   尽可能接近真实状态 【注意】 一定要把battery_sos记入flash，否则下次上电会跳变
 * @param  first: 是否首次 0--否  1--首次
 */
void power_bat_state_handle(bool first, uint16_t bat_vol)
{
    power_bat_state_t bat_state;

    // 首次需要处理，根据上次关机时的值进行对比。
    if (get_bat_vol() == 0 || get_bat_vol() < 1000)
    {
        set_bat_vol(bat_vol);
        first = true;
    }

    if (get_usb_state())
    {
        // 减去充电过程中的虚压,即将充满时，虚压会越来越小，故虚压减掉
        if (get_bat_vol() > LS_CHARGE_VOLTAGE_OFFSET && get_bat_vol() < 3950)
        {
            if (get_bat_soc_val() == BATTERY_MIN_SOC && first)
            {
            }
            else
            {
                reduce_bat_vol(LS_CHARGE_VOLTAGE_OFFSET);
            }
        }
        else if (get_bat_vol() > LS_CHARGE_VOLTAGE_OFFSET && get_bat_vol() >= 3950)
        {
            reduce_bat_vol(LS_CHARGE_VOLTAGE_OFFSET2);
        }
        power_bat_sos_handle(first);
        bat_state = app_power_get_bat_state(get_bat_soc_val(), get_usb_state());
        // 只有充电时，电池状态才能递增
        if (bat_state > get_bat_state())
        {
            set_bat_state(bat_state);
        }
    }
    else
    {
        if (get_bat_vol() < 1000 && get_bat_vol() != 0)
        {
            set_bat_soc_val(0);
            set_bat_state(POWER_SHUTDOWN_BATTERY);
            return;
        }
        power_bat_sos_handle(first);
        bat_state = app_power_get_bat_state(get_bat_soc_val(), get_usb_state());
        // 未充电时，电池状态不能递增
        if ((bat_state < get_bat_state()) || (get_bat_state() == 0 && first))
        {
            set_bat_state(bat_state);
        }
    }
}

uint16_t get_bat_full_vol_model_val(void)
{
    return g_battery_data_val[BATTERY_DATA_NUM - 1];
}
